import { LanguageServiceDefaults } from './_.contribution';
import * as languageFeatures from './languageFeatures';
import { Uri, IDisposable, languages } from './fillers/monaco-editor-core';

export function setupLanguageMode<T extends languageFeatures.IWorker>(
	defaults: LanguageServiceDefaults
): IDisposable {
	const disposables: IDisposable[] = [];
	const providers: IDisposable[] = [];

	function registerProviders(): void {
		const { languageId, modeConfiguration } = defaults;

		disposeAll(providers);
		//NOTE diagnostics
		providers.push(
			new languageFeatures.DiagnosticsAdapter(languageId, worker, defaults.onDidChange)
		);

		//NOTE completion
		providers.push(
			languages.registerCompletionItemProvider(
				languageId,
				new languageFeatures.CompletionAdapter(worker, defaults.completionTriggerCharacters)
			)
		);

		//NOTE hover
		providers.push(
			languages.registerHoverProvider(languageId, new languageFeatures.HoverAdapter(worker))
		);

		//NOTE formatting
		providers.push(
			languages.registerDocumentFormattingEditProvider(
				languageId,
				new languageFeatures.DocumentFormattingEditProvider(worker)
			)
		);
	}

	registerProviders();

	disposables.push(asDisposable(providers));

	return asDisposable(disposables);
}

function asDisposable(disposables: IDisposable[]): IDisposable {
	return { dispose: () => disposeAll(disposables) };
}

function disposeAll(disposables: IDisposable[]) {
	while (disposables.length) {
		disposables.pop()?.dispose();
	}
}
